/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-12-01     MXH        the first version
 */

#include <rtthread.h>
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#include "fal.h"
#include "drv_spi.h"

#ifdef BSP_USING_SOFT_SPI1
#include "drv_soft_spi.h"
#endif  /* BSP_USING_SOFT_SPI1 */

#ifdef BSP_USING_SPI_FLASH

static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, const uint8_t *buf, size_t size);
static int erase(long offset, size_t size);

static sfud_flash_t gd25q128_dev = NULL;
struct fal_flash_dev gd25q128_flash =
{
    SPI_FLASH_NAME,            /* Flash 设备的名字 */
    0,                          /* 对 Flash 操作的起始地址：0x00000000 */
    (8 * 1024 * 1024),           /* Flash 的总大小：8 MB */
    4096,                       /* Flash 块/扇区大小：4096 */
    {
            init,      /* init 函数 */
            read,               /* read 函数 */
            write,              /* write 函数 */
            erase               /* erase 函数 */
    },
    1
};

static int rt_hw_spi_flash_init(void)
{
    /* PB12--->CS */
    rt_hw_spi_device_attach(SPI_FLASH_BUS_NAME, SPI_FLASH_DEVICE_NAME, GPIOB, GPIO_Pin_12);
    if (RT_NULL == rt_sfud_flash_probe(SPI_FLASH_NAME, SPI_FLASH_DEVICE_NAME))
    {
        NVIC_SystemReset();
        return -RT_ERROR;
    }

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);


static int init(void)
{
#ifdef RT_USING_SFUD
    gd25q128_dev = rt_sfud_flash_find_by_dev_name(SPI_FLASH_NAME);

    if(gd25q128_dev)
    {
        LOG_D("find flash dev %s.", gd25q128_dev->name);
    }
    else
    {
        LOG_E("don't find flash dev %s.", gd25q128_dev->name);
    }
#else
    /* bare metal platform */
    extern sfud_flash sfud_norflash0;
    gd25q128_dev = &sfud_norflash0;
#endif

    if (NULL == gd25q128_dev)
    {
        return -RT_ERROR;
    }

    /* update the flash chip information */
    gd25q128_flash.blk_size = gd25q128_dev->chip.erase_gran;
    gd25q128_flash.len = gd25q128_dev->chip.capacity;

    return RT_EOK;
}

static int read(long offset, uint8_t *buf, size_t size)
{
    RT_ASSERT(gd25q128_dev);
    RT_ASSERT(gd25q128_dev->init_ok);
    sfud_read(gd25q128_dev, gd25q128_flash.addr + offset, size, buf);


    return size;
}

static int write(long offset, const uint8_t *buf, size_t size)
{
    RT_ASSERT(gd25q128_dev);
    RT_ASSERT(gd25q128_dev->init_ok);
    if (sfud_write(gd25q128_dev, gd25q128_flash.addr + offset, size, buf) != SFUD_SUCCESS)
    {
        return -RT_ERROR;
    }

    return size;
}


static int erase(long offset, size_t size)
{
    RT_ASSERT(gd25q128_dev);
    RT_ASSERT(gd25q128_dev->init_ok);
    if (sfud_erase(gd25q128_dev, gd25q128_flash.addr + offset, size) != SFUD_SUCCESS)
    {
        return -RT_ERROR;
    }

    return size;
}
#endif/* end of BSP_USING_SOFT_SPI_FLASH */
